/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ALKES_WIN32APP_APPLICATION_H_INCLUDED_
#define ALKES_WIN32APP_APPLICATION_H_INCLUDED_

#include "alkes.h"
#include "alkes/win32app/Win32EventDriver.h"
#include "alkes/win32app/Win32EventDelegator.h"
#include "alkes/win32app/Win32EventDrivenModel.h"

namespace alkes {

/** Application class.

@tparam T Graphics traits.
@tparam M Mainloop traits.
*/
template<class T, class M = Win32EventDrivenModel>
class Application
    : public TApplication< Application<T, M> >
{
public:
    Application(const char* title);
    virtual ~Application();

    bool initialize(int argc, char** argv);
    void finalize();

    HWND getHWND();
    IEventDriver* getIEventDriver();
    IEventDispatcher* getIEventDispatcher();
    typename T::GraphicsType* getGraphics();
    typename T::ScreenType* getScreen();

public:
    virtual void onMouseMove(uint16_t x, uint16_t y);
    virtual void onLButtonDown();
    virtual void onResize(uint16_t width, uint16_t height);

private:
    const char* title_;
    Win32EventDriver<T, M> driver_;
    Win32EventDelegator< Application<T, M> > dispatcher_;
};

template<class T, class M>
Application<T, M>::Application(const char* title)
: title_(title)
{
    dispatcher_.setTarget(this);
}

template<class T, class M>
Application<T, M>::~Application()
{
}

template<class T, class M>
HWND Application<T, M>::getHWND()
{
    return driver_.getHWND();
}

template<class T, class M>
IEventDriver* Application<T, M>::getIEventDriver()
{
    return &driver_;
}

template<class T, class M>
IEventDispatcher* Application<T, M>::getIEventDispatcher()
{
    return &dispatcher_;
}

template<class T, class M>
typename T::GraphicsType* Application<T, M>::getGraphics()
{
    return driver_.getGraphics();
}

template<class T, class M>
typename T::ScreenType* Application<T, M>::getScreen()
{
    return driver_.getScreen();
}

template<class T, class M>
bool Application<T, M>::initialize(int /*argc*/, char** /*argv*/)
{
    return driver_.initialize(getWidth(), getHeight(), title_);
}

template<class T, class M>
void Application<T, M>::finalize()
{
    driver_.finalize();
}

template<class T, class M>
void Application<T, M>::onMouseMove(uint16_t /*x*/, uint16_t /*y*/)
{
}

template<class T, class M>
void Application<T, M>::onLButtonDown()
{
}

template<class T, class M>
void Application<T, M>::onResize(uint16_t /*width*/, uint16_t /*height*/)
{
}


}

#endif
